#
# Copyright (c) 2023 supercell
#
# SPDX-License-Identifier: BSD-3-Clause
#

module Luce
  # :nodoc:
  @@empty_pattern = Regex.new(%q{^(?:[ \t]*)$})
  # :nodoc:
  @@setext_pattern = Regex.new(%q{^[ ]{0,3}(=+|-+)\s*$})
  # :nodoc:
  @@header_pattern =
    Regex.new(%q{^ {0,3}(#{1,6})(?:[ \x09\x0b\x0c].*?)?(?:\s(#*)\s*)?$})
  # :nodoc:
  @@blockquote_pattern = Regex.new(%q{^[ ]{0,3}>[ \t]?.*$})
  # :nodoc:
  @@indent_pattern = Regex.new(%q{^(?:    | {0,3}\t)(.*)$})
  # :nodoc:
  @@code_fence_pattern =
    Regex.new(%q{^([ ]{0,3})(?:(?<backtick>`{3,})(?<backtickInfo>[^`]*)|(?<tilde>~{3,})(?<tildeInfo>.*))$})
  # :nodoc:
  @@blockquote_fence_pattern = Regex.new(%q{^>{3}\s*$})
  # :nodoc:
  @@hr_pattern = Regex.new(%q{^ {0,3}([-*_])[ \t]*\1[ \t]*\1(?:\1|[ \t])*$})
  # :nodoc:
  @@list_pattern = Regex.new(%q{^[ ]{0,3}(?:(\d{1,9})[\.)]|[*+-])(?:[ \t]+(.*))?$})
  # :nodoc:
  @@table_pattern =
    Regex.new(%q<^[ ]{0,3}\|?([ \t]*:?\-+:?[ \t]*\|[ \t]*)+([ \t]|[ \t]*:?\-+:?[ \t]*)?$>)
  # :nodoc:
  @@footnote_pattern = Regex.new(%q{(^[ ]{0,3})\[\^([^\] \r\n\x00\t]+)\]:[ \t]*})
  # :nodoc:
  @@dummy_pattern = Regex.new("")
  # :nodoc:
  @@named_tag_definition : String = "<" +     # Opening tag begins.
    "[a-z][a-z0-9-]*" +                       # Tag name.
    %q{(?:\s+} +                              # Attribute begins, see https://spec.commonmark.org/0.30/#attribute.
    "[a-z_:][a-z0-9._:-]*" +                  # Attribute name, see https://spec.commonmark.org/0.30/#attribute-name
    "(?:" +                                   #
    %q{\s*=\s*} +                             # Attribute value specification, see https://spec.commonmark.org/0.30/#attribute-value-specification.
    %q{(?:[^\s"'=<>`]+?|'[^']*?'|"[^"]*?")} + # Attribute value, see https://spec.commonmark.org/0.30/#unquoted-attribute-value.
    ")?)*" +                                  # Attribute ends.
    %q{\s*/?>} +                              # Opening tag ends.
    "|" +                                     # Or
    %q{</[a-z][a-z0-9-]*\s*>}                 # Closing tag, see https://spec.commonmark.org/0.30/#closing-tag.

  # :nodoc:
  @@html_block_pattern = Regex.new(
    "^ {0,3}(?:" +
    "<(?<condition_1>pre|script|style|textarea)" +
    %q{(?:\s|>|$)} +
    "|" +
    "(?<condition_2><!--)" +
    "|" +
    %q{(?<condition_3><\?)} +
    "|" +
    "(?<condition_4><![a-z])" +
    "|" +
    %q{(?<condition_5><!\[CDATA\[)} +
    "|" +
    "</?(?<condition_6>address|article|aside|base|basefont|blockquote|body|" +
    "caption|center|col|colgroup|dd|details|dialog|dir|DIV|dl|dt|fieldset|" +
    "figcaption|figure|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|" +
    "header|hr|html|iframe|legend|li|link|main|menu|menuitem|nav|noframes|ol|" +
    "optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|" +
    "thead|title|tr|track|ul)" +
    %q{(?:\s|>|/>|$)} +
    "|" +
    # Here we are more restrictive than the Commonmark definition (Rule #7).
    # Otherwise some raw HTML test cases will fail, for example:
    # https://spec.commonmark.org/0.30/#example-618.
    # Because if a line is treated as an HTML block, it will output as Text node
    # directly, the RawHtmlSyntax does not have a chance to validate if this
    # HTML tag is legal or not.
    "(?<condition_7>(?:#{@@named_tag_definition})\\s*$))",
    Regex::Options::IGNORE_CASE)

  # See https://spec.commonmark.org/0.30/#unicode-whitespace-character.
  @@ascii_punctuation_characters = %q{!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~}

  @@ascii_punctuation_escaped = %q{!"#$%&'()*+,\-./:;<=>?@\[\\\]^_`{|}~}

  # https://spec.commonmark.org/0.30/#entity-and-numeric-character-references
  @@html_characters_pattern = Regex.new("&(?:([a-z0-9]+)|#([0-9]{1,7})|#x([a-f0-9]{1,6}));",
    Regex::Options::IGNORE_CASE)

  # :nodoc:
  @@link_reference_definition_pattern = Regex.new(%q{^[ ]{0,3}\[})

  # :nodoc:
  @@alert_pattern = Regex.new(%q{^\s{0,3}>\s{0,3}\\?\[!(note|tip|important|caution|warning)\\?\]\s*$},
    Regex::Options::IGNORE_CASE)

  # The line contains only whitespace or is empty
  def self.empty_pattern : Regex
    @@empty_pattern
  end

  # A series of `=` or `-` (on the next line) define setext-style headers.
  def self.setext_pattern : Regex
    @@setext_pattern
  end

  # Leading (and trailing) `#` define atx-style headers.
  #
  # Starts with 1-6 unescaped `#` characters which must not be followed
  # by a non-space character. Line may end with any number of `#`
  # characters.
  def self.header_pattern : Regex
    @@header_pattern
  end

  # The line starts with `>` with one optional space after.
  def self.blockquote_pattern : Regex
    @@blockquote_pattern
  end

  # A line indented four spaces. Used for code blocks and lists.
  def self.indent_pattern : Regex
    @@indent_pattern
  end

  # Fenced code block.
  def self.code_fence_pattern : Regex
    @@code_fence_pattern
  end

  # Fenced blockquotes
  def self.blockquote_fence_pattern : Regex
    @@blockquote_fence_pattern
  end

  # Three or more hyphens, asterisks or underscores by themselves.
  #
  # Note that a line like `----` is valid as both HR and SETEXT. In
  # case of a tie, SETEXT should win.
  def self.hr_pattern : Regex
    @@hr_pattern
  end

  # **Unordered list**
  # A list starting with one of these markers: `-`, `*`, `+`. May have up to
  # three leading spaces before the marker and any number of spaces or tabs
  # after.
  #
  # **Ordered list**
  # A line starting with a number like `123.`. May have up to three leading
  # spaces before the marker and any number of spaces or tabs after.
  def self.list_pattern : Regex
    @@list_pattern
  end

  # A line of hyphens separated by at least one pipe.
  def self.table_pattern : Regex
    @@table_pattern
  end

  # A line starting with `[^` and contains with `]:`, but without special chars
  # (`\] \r\n\x00\t`) between. Same as [GFM](https://github.com/github/cmark-gfm/blob/39ca0d9/src/scanners.re#L318).
  def self.footnote_pattern : Regex
    @@footnote_pattern
  end

  # A pattern which should never be used.
  #
  # It just satisfies non-nullability of pattern methods.
  def self.dummy_pattern : Regex
    @@dummy_pattern
  end

  # A `String` pattern to match a named tag like `<table>` or `</table>`.
  def self.named_tag_definition : String
    @@named_tag_definition
  end

  # A pattern to match the start of an HTML block.
  #
  # The 7 conditions here correspond to the 7 start conditions in the Commonmark
  # specification one by one: https://spec.commonmark.org/0.30/#html-block.
  def self.html_block_pattern : Regex
    @@html_block_pattern
  end

  # ASCII punctuation characters.
  def self.ascii_punctuation_characters : String
    @@ascii_punctuation_characters
  end

  # ASCII punctuation characters with some characters escaped, in order to be
  # used in the RegExp character set.
  def self.ascii_punctuation_escaped : String
    @@ascii_punctuation_escaped
  end

  # A pattern to match HTML entity references and numeric character references.
  def self.html_characters_pattern : Regex
    @@html_characters_pattern
  end

  # A line starts with `[`.
  def self.link_reference_definition_pattern : Regex
    @@link_reference_definition_pattern
  end

  # Alert type patterns.
  #
  # A alert block is similar to a blockquote, starts with `> [!TYPE]`, and only
  # 5 types are supported (case-insensitive).
  def self.alert_pattern : Regex
    @@alert_pattern
  end
end
